iT邦幫忙

2024 iThome 鐵人賽

DAY 25
0

終於進到實作環節啦——
之前在Codrops曾看到用React Three Fiber做出酷炫3D效果的案例,就想說一定要趁著鐵人賽嘗試。

這次參考的程式碼中出現了interface Props,而這其實是TypeScript的語法。雖說日後若真的靠前端糊口飯吃,我想會有很高的機率寫到TS,不過這邊還是先以JS為主,找時間再深造TypeHero。

打鐵趁熱,首先自然要載three和@react-three/fiber。
此時的畫面沒占滿,所以到CSS設定main的大小。
接著導入Canvas。

// App.js
import { Canvas } from "@react-three/fiber";
import Ring from "./ring";
import "./styles.css";

export default function App() {
  return (
    <main>
      <Canvas>
        <Ring radius={2} height={4} segments={32} />
      </Canvas>
    </main>
  );
}
// ring.js
export default function Ring({ radius, height, segments }) {
  return (
    <mesh>
      <cylinderGeometry args={[radius, radius, height, segments]} />
      <meshBasicMaterial />
    </mesh>
  );
}

很好,我們有個圓柱體了。
這時為了上字,就要來引入,和R3F同樣由Poimandres開發的超強外掛drei。

// App.js
// 加上測試用的text
<Ring
  radius={2}
  height={4}
  segments={32}
  text="X X X X X X X X X X X X X X X X X X X X X X X X X X X X "
/>
// ring.js
import { Text } from "@react-three/drei";

export default function Ring({ text = "", radius, height, segments }) { 
  const textPositions = [];
  const angleStep = (2 * Math.PI) / text.length;
  for (let i = 0; i < text.length; i++) {
    const angle = i * angleStep;
    const x = radius * Math.cos(angle);
    const z = radius * Math.sin(angle);
    textPositions.push({ x, z });
  }
}

這裡有些小細節可以注意:
像是text如果沒先預設成空字串會沒辦法讀它的length。
另一個小卡關的是要const textPositions = [],不能設成 [0, 0]。

// ring.js
return (
    <group>
      <mesh>
        <cylinderGeometry args={[radius, radius, height, segments]} />
        <meshBasicMaterial />
      </mesh>
      {text.split("").map((char, index) => (
        <Text
          key={index}
          position={[textPositions[index].x, 0, textPositions[index].z]}
          rotation={[0, -angleStep * index + Math.PI / 2, 0]}
          fontSize={0.3}
          lineHeight={1}
          letterSpacing={0.02}
          color="white"
          textAlign="center"
        >
          {char}
        </Text>
      ))}
    </group>
);

現在圓柱體外有字了。
一起用useRef + useFrame(R3F的Hook),來讓畫面轉起來。

// ring.js
const ref = useRef();
useFrame(() => {
    ref.current.rotation.x += 0.01;
    ref.current.rotation.y += 0.01;
    ref.current.rotation.z += 0.01;
});

記得也要幫group加上ref喔。
再來把<meshBasicMaterial />換成<MeshTransmissionMaterial/>,就行啦。
透射材質讓整個頁面都高級起來了呢。

但學習不能只停留在複刻大神的心血,更要向外延伸。
而摸索和試錯也正是寫程式最令人煩躁、也最令人滿足的時光。

加入自己很喜歡、可以讓使用者自由轉動場景的基本功能<OrbitControls />後,一時間我最想做的更動即是調整字型,沒料到想來簡單的課題卻耗了段時間。

Reference

shalildev / Text Ring


上一篇
【Day24】Good Writing
下一篇
【Day26】R3F 2
系列文
【現在學React還來得及嗎?】30天Takeaway分享30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言